package hxy.dragon.ktor.plugins

import com.fasterxml.jackson.databind.SerializationFeature
import io.ktor.serialization.jackson.jackson
import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.Application
import io.ktor.server.application.install
import io.ktor.server.application.log
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.response.respond
import io.ktor.server.routing.get
import io.ktor.server.routing.routing
import kotlinx.serialization.ContextualSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.JsonUnquotedLiteral
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.double
import kotlinx.serialization.json.doubleOrNull
import kotlinx.serialization.json.int
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.serializer


@OptIn(ExperimentalSerializationApi::class)
internal object DynamicLookupSerializer : KSerializer<Any> {
    override val descriptor: SerialDescriptor =
        ContextualSerializer(Any::class, null, emptyArray()).descriptor

    @Suppress("UNCHECKED_CAST")
    @OptIn(InternalSerializationApi::class)
    override fun serialize(encoder: Encoder, value: Any) {

        when (value) { // 没有switch
            null -> encoder.encodeNull()
            is String -> {
                if (value.isNotBlank()) {
                    val jsonUnquotedLiteral = JsonPrimitive(value.takeIf { it != "null" && it.isNotBlank() })
//                 下面这个，字符串不带双引号，构建的json格式字符串不正确
//                val jsonUnquotedLiteral = JsonUnquotedLiteral(value.takeIf { it != "null" && it.isNotBlank() })
                    encoder.encodeSerializableValue(JsonPrimitive.serializer(), jsonUnquotedLiteral)
                } else {
                    encoder.encodeNull()
                }
            }

            is ArrayList<*> ->
                encoder.encodeSerializableValue(
                    ListSerializer(DynamicLookupSerializer),
                    value.filterNotNull() // 过滤空值
                )

            else -> {
                val actualSerializer =
                    encoder.serializersModule.getContextual(value::class) ?: value::class.serializer()
                encoder.encodeSerializableValue(actualSerializer as KSerializer<Any>, value)
            }

        }

    }

    override fun deserialize(decoder: Decoder): Any {
        val jsonDecoder = decoder as? JsonDecoder ?: throw SerializationException("需要 JSON 解码器")
        val element = jsonDecoder.decodeJsonElement()

        return when (element) {
            // 允许基本类型
            is JsonPrimitive -> parsePrimitive(element)
            // 严格禁止对象和数组
            is JsonObject, is JsonArray -> throw SerializationException("复杂类型反序列化被禁用")
            // 不允许 null（因返回类型为 Any）
            is JsonNull -> throw SerializationException("不允许空值")
        }
    }
}

/** 解析原始类型（String/Int/Double/Boolean） */
private fun parsePrimitive(element: JsonPrimitive): Any {
    return when {
        element.isString -> element.content // 字符串
        element.booleanOrNull != null -> element.boolean // 布尔值
        element.intOrNull != null -> element.int // 优先解析为 Int
        element.doubleOrNull != null -> element.double // 其次解析为 Double
        else -> throw SerializationException("未知的原始类型: ${element.content}")
    }
}


fun Application.configureSerialization() {
    install(ContentNegotiation) {
        json(Json {
            prettyPrint = true
            isLenient = true
            ignoreUnknownKeys = true
            encodeDefaults = true
            serializersModule = SerializersModule {
                contextual(Any::class, DynamicLookupSerializer) // 自定义序列化器
            }
        })
        jackson {
            enable(SerializationFeature.INDENT_OUTPUT)
        }
    }
    routing {
        get("/json/kotlinx-serialization") {
            log.info("kotlinx-serialization序列化实现？")
            call.respond(mapOf("hello" to "world"))
        }
        get("/json/jackson") {
            log.info("jackson序列化实现？")
            call.respond(mapOf("hello" to "world"))
        }
    }
}
